//
//  dataBase.m
//  ElektroM
//
//  Created by Michael on 10.10.09.
//  Copyright 2009 Artgruppe inc. All rights reserved.
//

#import "dataBase.h"
#import "Constants.h"


@implementation dataBase
@synthesize databaseName, databasePath, namePrefix;

#pragma mark -
#pragma mark Initialization and Stuff
-(void) initialization
{
	NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
				 NSUserDomainMask, YES);
	NSString *documentsDir = [documentPaths objectAtIndex:0];
	databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
	
	// Execute the "checkAndCreateDatabase" function
	[self checkAndCreateDatabase];
	
	// Query the database for all animal records and construct the "animals" array
	//[self readFromDatabase];
	//aStationsNames=nil;
	_bStationsInAlpabeticalOrderWereLoaded=false;

	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

	NSString* sStringsLoad = [defaults objectForKey: kStringType];

	if([sStringsLoad isEqualToString: @"locale"])
	{
	    // try to find out what locale we use...
	    NSLocale *locale = [NSLocale currentLocale];
	    if([[locale localeIdentifier] isEqualToString: @"ru_RU"])
		_bUseEnglishNames=false;
	    else
		_bUseEnglishNames=true;
	}
	else{
	    if([sStringsLoad isEqualToString: @"ru"])
		_bUseEnglishNames=false;
	    else
		_bUseEnglishNames=true;
	}
}

-(void) checkAndCreateDatabase
{
	// Check if the SQL database has already been saved to the users phone, if not then copy it over
	BOOL success;
	
	// Create a FileManager object, we will use this to check the status
	// of the database and to copy it over if required
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	// Check if the database has already been created in the users filesystem
	success = [fileManager fileExistsAtPath:databasePath];
	
	// If the database already exists then return without doing anything
	if(success) return;
	
	// If not then proceed to copy the database from the application to the users filesystem
	
	// Get the path to the database in the application package
	NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] 
						 stringByAppendingPathComponent:databaseName];
	
	// Copy the database from the package to the users filesystem
	[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
	
	[fileManager release];
}

#pragma mark -
#pragma mark CentersRailways
-(NSArray*) readCentersAsNSArray
{
    return [self  readCentersAsNSArrayLoadRailways: true];
}

-(NSArray*) readCentersAsNSArrayLoadRailways:(bool)bRailways {
	// Setup the database object
	sqlite3 *database;
	NSMutableArray* aiCentersX;
	NSMutableArray* aiCentersY;
	// Open the database from the users filessytem
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
		
		sqlite3_stmt *compiledStatement;
		// Setup the SQL Statement and compile it for faster access
		// first find out, how many records do we have:
		NSString* strQuery;
		if(bRailways)
		    strQuery=[NSString stringWithFormat:@"select count(*) from %s_centers;", 
			[namePrefix UTF8String]];				
		else
		    strQuery=[NSString stringWithString: @"select count(*) from Knots_centers;"];				

		const char *sqlStatementHowMany = [strQuery UTF8String];
		if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
			    [self cleanCentersInfo];

			    nCentersCount=sqlite3_column_int(compiledStatement,0);
			    aiCentersX=[NSMutableArray arrayWithCapacity: nCentersCount];
			    aiCentersY=[NSMutableArray arrayWithCapacity: nCentersCount];
			}
			else{
			    sqlite3_finalize(compiledStatement);
			    sqlite3_close(database);
			    return NULL;
			}
		}
		sqlite3_finalize(compiledStatement);
		
		if(bRailways)
		    strQuery=[NSString stringWithFormat:@"select id, X, Y from %s_centers order by id;", 
			[namePrefix UTF8String]];
		else
		    strQuery=[NSString stringWithFormat:@"select station_id, dX, dY from Knots_centers order by station_id;" ];

		const char *sqlStatement = [strQuery UTF8String];		
		
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
			// Loop through the results and add them to the feeds array
			while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				// Read the data from the result row
			    [aiCentersX addObject: [NSNumber numberWithInt: 
				sqlite3_column_int(compiledStatement, 1)]];

			    [aiCentersY addObject: [NSNumber numberWithInt: 
				sqlite3_column_int(compiledStatement, 2)]];
			}
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);		
	}
	sqlite3_close(database);


	// set the methods...
	if(bRailways){
	    _aiCentersX = aiCentersX;
	    [_aiCentersX retain];
	    _aiCentersY = aiCentersY;
	    [_aiCentersY retain];
	}
	else
	{
	    _aiUCentersX = aiCentersX;
	    [_aiUCentersX retain];

	    _aiUCentersY = aiCentersY;
	    [_aiUCentersY retain];
	}
	
	if(bRailways)
	    return _aiCentersX;

	return _aiUCentersX;
}

-(void) cleanCentersInfo
{
    if(_aiUCentersX!=nil)
	[_aiUCentersX release];
    _aiUCentersX=nil;

    if(_aiUCentersY!=nil)
	[_aiUCentersY release];
    _aiUCentersY=nil;


    if(_aiCentersX!=nil)
	[_aiCentersX release];
    _aiCentersX=nil;

    if(_aiCentersY!=nil)
	[_aiCentersY release];
    _aiCentersY=nil;
}

-(NSArray*) getUCentersYAsNSArray
{
    return _aiUCentersY;
}

-(NSArray*) getCentersYAsNSArray
{
    return _aiCentersY;
}

-(NSArray*) getCentersXAsNSArray
{
    return _aiCentersX;
}

#pragma mark -
#pragma mark Time Table Railways
-(void) cleanTrainInfoAsNSArray
{
    if(_aiTrainStations!=nil)
	[_aiTrainStations release];
    if(_aiTrainTimes!=nil)
	[_aiTrainTimes release];
    if(_aiStationsNamesForTrains!=nil)
	[_aiStationsNamesForTrains release];

    _aiTrainTimes=nil;
    _aiTrainStations=nil;
    _aiStationsNamesForTrains=nil;
}

-(NSArray*) readTrainInfoAsNSArray:(NSString*)trainId 
{
    // arrays for times and stations:
    NSMutableArray* aiTrainTimes;
    NSMutableArray* aiTrainStations;
    NSMutableArray* aiStationNames;
    // Setup the database object
    sqlite3 *database;

    // Open the database from the users filessytem
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

	sqlite3_stmt *compiledStatement;
	// Setup the SQL Statement and compile it for faster access
	// first find out, how many records do we have:
	 NSString* strQuery=[NSString stringWithFormat:@" select  count(*) from %s_Trains where train_id like '", 
	     [namePrefix UTF8String]];				
	 strQuery=[strQuery stringByAppendingString:@"%"];
	 strQuery=[strQuery stringByAppendingString:trainId];
	 strQuery=[strQuery stringByAppendingString:@"%'"];
	 
	 const char *sqlStatementHowMany = [strQuery UTF8String];

	 //printf("Query: %s\n", sqlStatementHowMany);

	 if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
	     if(sqlite3_step(compiledStatement) == SQLITE_ROW) {

		 [self cleanTrainInfoAsNSArray];
		 _nTrainTimesCount=sqlite3_column_int(compiledStatement,0);				
		 aiTrainTimes=[NSMutableArray arrayWithCapacity: _nTrainTimesCount];
		 aiTrainStations=[NSMutableArray arrayWithCapacity: _nTrainTimesCount];
		 // I do not know exactly how many stations we have, 
		 // but what's the difference?
		 aiStationNames=[NSMutableArray arrayWithCapacity: _nTrainTimesCount];
	     }
	     else{
		 sqlite3_finalize(compiledStatement);
		 sqlite3_close(database);

		 return nil;			
	     }

	 }
	 // Release the compiled statement from memory
	 sqlite3_finalize(compiledStatement);		

	 strQuery=[NSString stringWithFormat:@" select station_id, time from %s_Trains where train_id like '", 
	     [namePrefix UTF8String]];		
	 strQuery=[strQuery stringByAppendingString:@"%"];
	 strQuery=[strQuery stringByAppendingString:trainId];
	 strQuery=[strQuery stringByAppendingString:@"%'"];
	 
	 const char *sqlStatement= [strQuery UTF8String];
	 //printf("Query Normal: %s; Count: %d\n", sqlStatement, _nTrainTimesCount);
	 if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
	     while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		 [aiTrainStations addObject: 
		     [NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 0)]];

		 [aiTrainTimes addObject:
		     [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
	     }
	 }
	 // Release the compiled statement from memory
	 sqlite3_finalize(compiledStatement);	

	 // then we have to read station names:
	 strQuery=[NSString stringWithFormat: @"select station_name from %@_stations", 
	     namePrefix];

	 if(sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK) {
	     while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		 
		 [aiStationNames addObject:
		     [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]];
	     }
	 }
	 // Release the compiled statement from memory
	 sqlite3_finalize(compiledStatement);
    }
    sqlite3_close(database);	

    _aiTrainTimes = aiTrainTimes;
    [_aiTrainTimes retain];

    _aiTrainStations = aiTrainStations;
    [_aiTrainStations retain];

    _aiStationsNamesForTrains=aiStationNames;
    [_aiStationsNamesForTrains retain];

    return _aiTrainTimes;
}

-(NSArray*) getTrainStations
{
    return _aiTrainStations;
}

-(NSArray*) getTrainStationsNames
{
    return _aiStationsNamesForTrains;
}

-(void) releaseAllElementsOfTimeTableAsNSArray
{
    if(_aiTimes!=nil)
    [_aiTimes release];
    if(_aiStartStations!=nil)
    [_aiStartStations release];
    if(_aiEndStations!=nil)
    [_aiEndStations release];
    if(_aiTrainIds!=nil)
    [_aiTrainIds release];
    if(_aiiTrainInfo!=nil)
	[_aiiTrainInfo release];

    _aiTimes=nil;
    _aiStartStations=nil;
    _aiEndStations=nil;
    _aiTrainIds=nil;
    _aiiTrainInfo = nil;
}

-(NSArray*) readTimeTableAsNSArray:(int)nStation_id withTime:(NSString*)aCurTime withDirection:(int)nDirection
{
    NSMutableArray* aiStartStations;
    NSMutableArray* aiEndStations;
    NSMutableArray* aiTimes;
    NSMutableArray* aiTrainIds;
    NSMutableArray* aiiTrainInfo;

    // Setup the database object
    sqlite3 *database;
    // Open the database from the users filessytem
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

	sqlite3_stmt *compiledStatement;
	// Setup the SQL Statement and compile it for faster access
	// first find out, how many records do we have:
	 NSString* strQuery=[NSString stringWithFormat:@"select  count(*), CAST(time AS TIME) AS TimeColumn from %s_TimeTable"
	     " where station_id=%d and direction=%d and TimeColumn > CAST(time('%s') as TIME)", 
	     [namePrefix UTF8String], nStation_id, nDirection, [aCurTime UTF8String]];				
	 const char *sqlStatementHowMany = [strQuery UTF8String];
	 if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
	     if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		 nTimeTableCount=sqlite3_column_int(compiledStatement,0);
		 if(nTimeTableCount==0 && !_bReloadDayAndNight)
		 {
		     // set the flag for not cycling infinitely on the stations, 
		     // where there are no records:
		     _bReloadDayAndNight=true;
		     //reload data with data from the beginning of the day:
		     return [self readTimeTableAsNSArray: nStation_id withTime: @"00:00:00" withDirection: nDirection];
		 }
		 [self releaseAllElementsOfTimeTableAsNSArray];
		 _bReloadDayAndNight=false;

		 aiTimes = [NSMutableArray arrayWithCapacity: nTimeTableCount];
		 aiTrainIds = [NSMutableArray arrayWithCapacity: nTimeTableCount];
		 aiStartStations = [NSMutableArray arrayWithCapacity: nTimeTableCount];
		 aiEndStations = [NSMutableArray arrayWithCapacity: nTimeTableCount];
		 aiiTrainInfo = [NSMutableArray arrayWithCapacity: nTimeTableCount];
	     }
	     else{
		 sqlite3_finalize(compiledStatement);
		 sqlite3_close(database);

		 return NULL;
	     }
	 }
	 sqlite3_finalize(compiledStatement);
	 //printf("nStationCount: %d\n", nStationsCount);		
	 // very, very big query:
    strQuery=[NSString stringWithFormat:@"select station_id, time, direction, train_id, station_start_id, station_end_id, CAST(time AS TIME) AS TimeColumn, info from %s_TimeTable where station_id=%d and direction=%d and TimeColumn > CAST(time('%s') as TIME)",
	[namePrefix UTF8String], 
	nStation_id, nDirection, [aCurTime UTF8String]];

    // adding another request:
		strQuery=[NSString stringWithFormat:@"select T.station_id, time, direction, train_id,   K.station_name as StartStation, T.station_end_id, KK.station_name as EndStation, T.info from (%@) T, %s_stations K join %s_stations KK on KK.station_id-1=T.station_end_id where K.station_id-1=T.station_start_id", 
		    strQuery, [namePrefix UTF8String], [namePrefix UTF8String]];

		const char *sqlStatement = [strQuery UTF8String];		
		//printf("Query to readTimeTable: %s\n", sqlStatement);
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
		    // Loop through the results and add them to the feeds array
		    while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
			// Read the data from the result row
			[aiTimes addObject: 
	    			[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];

			[aiTrainIds addObject: 
	       			[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)]];


			[aiStartStations addObject: 
		    		[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 4)]];
			
			[aiEndStations addObject: 
		  		[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 6)]];

			[aiiTrainInfo addObject:
			[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 7)]];
		    }
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);		
    }
    sqlite3_close(database);	

    _aiTimes = aiTimes;
    [_aiTimes retain];

    _aiTrainIds=aiTrainIds;
    [_aiTrainIds retain];

    _aiStartStations = aiStartStations;
    [_aiStartStations retain];

    _aiEndStations = aiEndStations;
    [_aiEndStations retain];

    _aiiTrainInfo = aiiTrainInfo;
    [_aiiTrainInfo retain];

    return _aiTimes;
}

-(NSArray*) getStartStationsAsNSArray
{
    return _aiStartStations;
}

-(NSArray*) getEndStationsAsNSArray
{
    return _aiEndStations;
}

-(NSArray*) getTrainInfoAsNSArray
{
    return _aiiTrainInfo;
}

-(NSArray*) getTrainIdsAsNSArray
{
    return _aiTrainIds;
}

-(NSString*) readTimeTableByCenterIdShort:(int)nCenterId withDirection:(int)nDirection
{
	NSString *aCurTime;	
	NSString *aCurDate;
	NSDate* CurDate=[NSDate date];
	NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc] init] autorelease];
	[timeFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
	[timeFormatter setDateStyle:NSDateFormatterNoStyle];	
	[timeFormatter setTimeStyle:NSDateFormatterMediumStyle];	
	
	aCurTime = [timeFormatter stringFromDate:CurDate];
	[timeFormatter setDateStyle:NSDateFormatterMediumStyle];
	[timeFormatter setTimeStyle:NSDateFormatterNoStyle];
	aCurDate = [timeFormatter stringFromDate:CurDate];
	
	NSDateFormatter *inputFormatter = [[[NSDateFormatter alloc] init] autorelease];
	[inputFormatter setDateFormat:@"dd.MM.yyyy HH.mm"];
	
	sqlite3 *database;
	int StationId;
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
		
		sqlite3_stmt *compiledStatement;
		// Setup the SQL Statement and compile it for faster access
		// first find out, how many records do we have:
		NSString* strQuery=[NSString stringWithFormat:@"select id from %s_centers where center_id=%d;", 
							[namePrefix UTF8String], nCenterId+1];				
		const char *sqlStatementHowMany = [strQuery UTF8String];
		//printf("Query to station id:%s\n", [strQuery UTF8String]);
		if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				StationId=sqlite3_column_int(compiledStatement,0);				
			}
			else{
			    sqlite3_finalize(compiledStatement);
			    sqlite3_close(database);			
				
				return @"??:??";
			}
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);

		strQuery=[NSString stringWithFormat:@"select time, direction, train_id, CAST(time AS TIME) AS TimeColumn from %s_TimeTable"
							 " where station_id=%d and direction=%d and TimeColumn > CAST(time('%s') as TIME)", 
							 [namePrefix UTF8String], StationId-1, nDirection, [aCurTime UTF8String]];
		const char *sqlStatement = [strQuery UTF8String];
		//printf("Query to station with time:%s\n", sqlStatement);
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
			while(sqlite3_step(compiledStatement) == SQLITE_ROW) {				
				NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
				NSString *aDate = [NSString stringWithFormat:@"%s %s", [aCurDate UTF8String],
								   [aName UTF8String]];
				//printf("aDate %s; CurDate: %s %s\n", [aDate UTF8String], [aCurDate UTF8String], [aCurTime UTF8String]);
				NSDate* dateInDb=[inputFormatter dateFromString:aDate];
				NSDate* laterDate=[dateInDb laterDate:CurDate];
							
				if([laterDate isEqualToDate:dateInDb])
				{
					//found later date, return it after some dancing:
					
					// Release the compiled statement from memory
					sqlite3_finalize(compiledStatement);	
					sqlite3_close(database);
					
					//[dateInDb release];
					//[aDate release];
					//[CurDate release];					
					//[aCurDate release];
					//[aCurTime release];					
					//[timeFormatter release];
					//[inputFormatter release];
					[aName retain];					
					
					return aName;
				}			
			}
		}	
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);	
		// if we are here, we have to return the first one date in the list:
		strQuery=[NSString stringWithFormat:@"select time from %s_TimeTable"
				 " where station_id=%d and direction=%d", 
				 [namePrefix UTF8String], StationId-1, nDirection];
		//printf("Query to station with time:%s\n", sqlStatement);
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
			    // take that string and return it...
			    NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
			    sqlite3_finalize(compiledStatement);
			    sqlite3_close(database);				
				
				[aName retain];		
				
			    return aName;
			}
		}
		sqlite3_finalize(compiledStatement);	

	}	
	sqlite3_close(database);
		
	return @"??.??";	
}


-(int)getTimeTableCount
{
	return nTimeTableCount;
}

-(NSString*) findTimeOfNearTrainWithFirstSt:(int)nFirstSt 
						   andSecondStation:(int)nSecond 
							  withDirection:(int)nDirection
{
	return [self  findTimeOfNearTrainWithFirstSt:nFirstSt 
					andSecondStation: nSecond 
					withDirection: nDirection
					 andTimeZero: false];
}

-(NSString*) findTimeOfNearTrainWithFirstSt:(int)nFirstSt 
			   andSecondStation:(int)nSecond 
			      withDirection:(int)nDirection
				andTimeZero: (bool)bZero
{
    NSString *aCurTime;	
    NSString *aCurDate;
    NSDate* CurDate=[NSDate date];
    NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc] init] autorelease];
    [timeFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
    [timeFormatter setDateStyle:NSDateFormatterNoStyle];	
    [timeFormatter setTimeStyle:NSDateFormatterMediumStyle];	

	if(!bZero)
		aCurTime = [timeFormatter stringFromDate:CurDate];
	else
		aCurTime=@"00:00:00";
	
    [timeFormatter setDateStyle:NSDateFormatterMediumStyle];
    [timeFormatter setTimeStyle:NSDateFormatterNoStyle];
    aCurDate = [timeFormatter stringFromDate:CurDate];

    NSDateFormatter *inputFormatter = [[[NSDateFormatter alloc] init] autorelease];
    [inputFormatter setDateFormat:@"dd.MM.yyyy HH.mm"];

    sqlite3 *database;    
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

	sqlite3_stmt *compiledStatement;
	// Setup the SQL Statement and compile it for faster access
	// first find out, how many records do we have:
	 NSString* strQuery;

	 strQuery=[NSString stringWithFormat:@"select time, direction, train_id, CAST(time AS TIME) AS TimeColumn from %s_TimeTable"
	     " where station_id=%d and direction=%d and TimeColumn > CAST(time('%s') as TIME)", 
	     [namePrefix UTF8String], nFirstSt, nDirection, [aCurTime UTF8String]];
	 const char *sqlStatement = [strQuery UTF8String];
	 //printf("Query to station with time:%s\n", sqlStatement);
	 if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
	     while(sqlite3_step(compiledStatement) == SQLITE_ROW) {				
		 NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
		 NSString *aDate = [NSString stringWithFormat:@"%s %s", [aCurDate UTF8String],
			  [aName UTF8String]];
		 //printf("aDate %s; CurDate: %s %s\n", [aDate UTF8String], [aCurDate UTF8String], [aCurTime UTF8String]);
		 NSDate* dateInDb=[inputFormatter dateFromString:aDate];
		 NSDate* laterDate=[dateInDb laterDate:CurDate];

		 if([laterDate isEqualToDate:dateInDb])
		 {
		     //found later date, return it after some dancing:

		     // Release the compiled statement from memory
		     // it's a candidate.. try it, if you can reach final station from that one...
		     NSString* sTrainId=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
		     NSString* sQuery2=[NSString stringWithFormat: @"select time from %@_Trains where train_id like '", 
			 namePrefix];

		     sQuery2=[sQuery2 stringByAppendingString: sTrainId];
		     sQuery2=[sQuery2 stringByAppendingString: @"'"];
		     sQuery2=[NSString stringWithFormat: @"%@ and station_id=%d", sQuery2, nSecond+1];

		     sqlite3_stmt *compiledStatementNew;
		     bool bFoundStation=false;
		     NSString* strTime;
		     if(sqlite3_prepare_v2(database, [sQuery2 UTF8String], -1, &compiledStatementNew, NULL) == SQLITE_OK){
			 if(sqlite3_step(compiledStatementNew)==SQLITE_ROW){
			     strTime=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatementNew, 0)];
			     bFoundStation=true;
			 }
			 sqlite3_finalize(compiledStatementNew);
		     }

		     if(bFoundStation){
			 sqlite3_finalize(compiledStatement);	
			 sqlite3_close(database);
			 _sDestinationTime=strTime;
			 [_sDestinationTime retain];

			 [aName retain];					

			 return aName;
		     }
		 }			
	     }
	 }	
	 sqlite3_finalize(compiledStatement);
    }	
    sqlite3_close(database);
	if(!bZero)
		return [self findTimeOfNearTrainWithFirstSt: nFirstSt 
							andSecondStation: nSecond 
							withDirection: nDirection
							andTimeZero: true];
	
    _sDestinationTime=@"??.??";
	[_sDestinationTime retain];
	return @"??.??";	
}

-(NSString*) getDestinationTime
{
    return _sDestinationTime;
}

#pragma mark -
#pragma mark Station Names Railways
-(NSArray*) readStationStructureAsNSArrayAndLoadAlsoNames:(bool)bLoadNames
{
	// Setup the database object
	sqlite3 *database;
	//NSMutableArray* array=[NSMutableArray alloc];
	/// station info we would leave as c-struct now... 
	NSMutableArray* aiNext;
	// keys for our nodes, because there are a lot of zero nodes
	// we would create a dictionary for the pair id - node;
	NSMutableArray* aiNodeKeys;
	NSMutableArray* aiNodes;
	NSDictionary* diNodes;

	NSMutableArray* aiStations;
	// Open the database from the users filessytem
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
		
		sqlite3_stmt *compiledStatement;
		// Setup the SQL Statement and compile it for faster access
		// first find out, how many records do we have:
		NSString* strQuery=[NSString stringWithFormat:@"select count(*) from %s_stations;", 
							[namePrefix UTF8String]];				
		const char *sqlStatementHowMany = [strQuery UTF8String];
		if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				nStationsCount=sqlite3_column_int(compiledStatement,0);
				aiNext = [NSMutableArray arrayWithCapacity: nStationsCount];
				aiNodes = [NSMutableArray array];
				aiNodeKeys = [NSMutableArray array];
				if(bLoadNames)
				    aiStations=[NSMutableArray arrayWithCapacity: nStationsCount];
			}
			else{
			    sqlite3_finalize(compiledStatement);
			    sqlite3_close(database);
			    return NULL;
			}
		}
		sqlite3_finalize(compiledStatement);

		if(!_bUseEnglishNames)
			strQuery=[NSString stringWithFormat:@"select station_id, station_name, next, node from %s_stations;", 
					  [namePrefix UTF8String]];
		else
			strQuery=[NSString stringWithFormat:@"select station_id, station_nameEng, next, node from %s_stations;", 
					  [namePrefix UTF8String]];
		
		const char *sqlStatement = [strQuery UTF8String];		
		//printf("Query to stations: %s\n", sqlStatement);
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
			// Loop through the results and add them to the feeds array
			while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				// Read the data from the result row	
				int nNode=sqlite3_column_int(compiledStatement, 3);

				[aiNext addObject: [NSNumber numberWithInt:sqlite3_column_int(compiledStatement, 2)-1]];
				if(nNode!=0)
				{
				    [aiNodes addObject: [NSNumber numberWithInt:nNode-1]];
				    [aiNodeKeys addObject: 
				  [NSNumber numberWithInt:sqlite3_column_int(compiledStatement, 0)-1]];
				}
				
				if(bLoadNames)
				    [aiStations addObject: [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
					//printf("id: %d; Station: %s Count: %d\n", nId,[aName UTF8String], count);
			}
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);			
	}
	sqlite3_close(database);


	_aiNext = aiNext;
	[_aiNext retain];

	diNodes = [NSDictionary dictionaryWithObjects: aiNodes forKeys: aiNodeKeys];
	_diNodes = diNodes;
	[_diNodes retain];


	if(bLoadNames){
	    _aiStationsNames=aiStations;
	    [_aiStationsNames retain];
	}
	
	return _aiNext;
}

-(NSDictionary*) getNodesOfStationsAsNSArray
{
    return _diNodes;
}

-(NSArray*) readStationNamesAsNSArray
{
    	NSString* strQuery;
	// Setup the database object
	sqlite3 *database;
	//NSMutableArray* array=[NSMutableArray alloc];
	/// station info we would leave as c-struct now... 
	NSMutableArray* aiStations;
	// Open the database from the users filessytem
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
		
		sqlite3_stmt *compiledStatement;
		// Setup the SQL Statement and compile it for faster access
		// first find out, how many records do we have:
		if(nStationsCount==0){
		    strQuery=[NSString stringWithFormat:@"select count(*) from %s_stations;", 
			[namePrefix UTF8String]];				
		const char *sqlStatementHowMany = [strQuery UTF8String];
		if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				nStationsCount=sqlite3_column_int(compiledStatement,0);
				aiStations=[NSMutableArray arrayWithCapacity: nStationsCount];
			}
			else{
				return NULL;
			}
		}
		sqlite3_finalize(compiledStatement);
		}
		else
		    aiStations=[NSMutableArray arrayWithCapacity: nStationsCount];

		//printf("nStationCount: %d\n", nStationsCount);
		strQuery=[NSString stringWithFormat:@"select station_id, station_name, next, node from %s_stations;", 
				  [namePrefix UTF8String]];
		const char *sqlStatement = [strQuery UTF8String];		
		//printf("Query to stations: %s\n", sqlStatement);
				
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
			// Loop through the results and add them to the feeds array
			while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
			    // Read the data from the result row	
			    [aiStations addObject: [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
			    //printf("id: %d; Station: %s Count: %d\n", nId,[aName UTF8String], count);
			}
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);			
	}
	sqlite3_close(database);

	_aiStationsNames=aiStations;
	[_aiStationsNames retain];
	
	return _aiStationsNames;
}

-(NSArray*) getStationNamesAsNSArray
{
    return _aiStationsNames;
}

-(NSString*) readStationNameByCenterId:(int)nCenterId
{
	sqlite3 *database;	
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
		
		sqlite3_stmt *compiledStatement;
		// Setup the SQL Statement and compile it for faster access
		// first find out, how many records do we have:
		NSString* strQuery=[NSString stringWithFormat:@"select id, station_name from %s_centers C join %s_stations S on S.station_id=C.id where center_id=%d;", 
							[namePrefix UTF8String], [namePrefix UTF8String], nCenterId+1];				
		const char *sqlStatementHowMany = [strQuery UTF8String];
		//printf("Query to station name:%s\n", [strQuery UTF8String]);
		if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				//StationId=sqlite3_column_int(compiledStatement,0);
				// Release the compiled statement from memory
				sqlite3_finalize(compiledStatement);
				sqlite3_close(database);
				return [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
			}
			else{
				//sqlite3_finalize(compiledStatement);
				sqlite3_close(database);
				return @"-";
			}
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);		
	}
	
	return @"-";
}

// returns info about amount of centers
-(int)getStationsCount
{
	return nStationsCount;
}

#pragma mark -
#pragma mark Buses 
-(void) releaseBusInfoResources
{
    if(_aiBusNames!=nil)
	[_aiBusNames release];
    _aiBusNames = nil;

    if(_aiBusInfo!=nil)
	[_aiBusInfo release];
    _aiBusInfo = nil;

    if(_aiBusTimes!=nil)
	[_aiBusTimes release];
    _aiBusTimes=nil;
}

-(NSArray*) readBusesInfoBySearchAsNSArray: (NSString*)sSearch
{
	// there are will be two kinds of queries: select count(*) and select *
	//UPPER(bus_info) as low_bus_info
	NSString* strQuery=@" from buses where ";
	strQuery=[self separateByColonesAndAddToQuery:strQuery splittingString:sSearch andFirst:true];
	strQuery=[self separateByColonesAndAddToQueryName: strQuery splittingString:sSearch andFirst:true];
	NSMutableArray* aiBusNames;
	NSMutableArray* aiBusTimes;
	NSMutableArray* aiBusInfos;
	/*
	   //I do not want to separate the string by the "-"-symbol...
	bool bFirst=true;
	for(id substring in array)
	{
		strQuery=[self separateByColonesAndAddToQuery:strQuery splittingString:substring andFirst:bFirst];
		if(bFirst)
			bFirst=false;
	}
	 */
	
	//printf("Query for buses is %s\n", [strQuery UTF8String]);
	// now we've got the query, try to get the strings:	
	sqlite3 *database;	
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
		
		sqlite3_stmt *compiledStatement;
		// Setup the SQL Statement and compile it for faster access
		// first find out, how many records do we have:
		NSString* strQueryCount=[NSString stringWithFormat:@"%@ %@", @"select count(*)", strQuery];

		const char *sqlStatementHowMany = [strQueryCount UTF8String];
		//printf("Query to station name:%s\n", [strQueryCount UTF8String]);
		if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
			if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
				//free the used memory:
				[self releaseBusInfoResources];

				_nBusCount=sqlite3_column_int(compiledStatement,0);
				//printf("Count: %d\n", _nBusCount);				
				// initialize needed data:
				aiBusInfos = [NSMutableArray arrayWithCapacity: _nBusCount];
				aiBusTimes = [NSMutableArray arrayWithCapacity: _nBusCount];
				aiBusNames = [NSMutableArray arrayWithCapacity: _nBusCount];
			}
			else{
			    sqlite3_finalize(compiledStatement);
			    sqlite3_close(database);
			    return nil;
			}
		}
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);
		//and now we'll read all info about strings:
		NSString* strQueryOne=[NSString stringWithFormat:@"%@ %@", @"select bus_name, bus_info, bus_time", strQuery];
		const char *sqlStatement = [strQueryOne UTF8String];
		//printf("Query to Buses:%s\n", [strQueryOne UTF8String]);
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
			while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
			    [aiBusNames addObject: 
		   		[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]];
			    [aiBusTimes addObject: 
		  		 [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)]];
			    [aiBusInfos addObject: 
		   		[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
			}
		}		
		// Release the compiled statement from memory
		sqlite3_finalize(compiledStatement);
	}	
	sqlite3_close(database);

	_aiBusInfo = aiBusInfos;
	[_aiBusInfo retain];

	_aiBusTimes = aiBusTimes;
	[_aiBusTimes retain];

	_aiBusNames = aiBusNames;
	[_aiBusNames retain];

	return _aiBusNames;	
}

-(NSArray*) getBusesInfoAsNSArray
{
    return _aiBusInfo;
}

-(NSArray*) getBusesTimesAsNSArray
{
    return _aiBusTimes;
}

#pragma mark -
#pragma mark Buses separation query
-(NSString*) separateByColonesAndAddToQuery:(NSString*)sQuery splittingString:(NSString*)sString andFirst:(bool)bFirstIn
{
	NSArray* ar=[[NSString stringWithUTF8String:[sString UTF8String]] componentsSeparatedByString:@" "];
	NSString* strOut;
	bool bFirst=bFirstIn;
	for(id str in ar)
	{
		if(bFirst)
		{
			// 
			strOut=[NSString stringWithFormat:@"%@ (bus_info like '%@", sQuery/* UTF8String]*/, @"%"];
			strOut=[strOut stringByAppendingString:str];
			strOut=[strOut stringByAppendingString:@"%'"];
			
			if([str length]>1)
			{
				// with upper letter:				
				strOut=[strOut stringByAppendingString:@" or bus_info like '%"];
				strOut=[strOut stringByAppendingString:[[str substringToIndex:1] uppercaseString]];
				strOut=[strOut stringByAppendingString:[[str substringFromIndex:1] lowercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];					
				// capitalized
				strOut=[strOut stringByAppendingString:@" or bus_info like '%"];
				strOut=[strOut stringByAppendingString:[str uppercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];	
				// lower string:				
				strOut=[strOut stringByAppendingString:@" or bus_info like '%"];
				strOut=[strOut stringByAppendingString:[str lowercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];				
			} 
			
			strOut=[strOut stringByAppendingString:@")"];			
			
			bFirst=false;			
		}
		else{
			strOut=[NSString stringWithFormat:@"%@ and (bus_info like '%@", strOut/*UTF8String]*/, @"%"];		
			strOut=[strOut stringByAppendingString:str];
			strOut=[strOut stringByAppendingString:@"%'"];
			
			 if([str length]>1)
			 {
			 // with upper letter:
			 
			 strOut=[strOut stringByAppendingString:@" or bus_info like '%"];
			 strOut=[strOut stringByAppendingString:[[str substringToIndex:1] uppercaseString]];
			 strOut=[strOut stringByAppendingString:[[str substringFromIndex:1] lowercaseString]];
			 strOut=[strOut stringByAppendingString:@"%'"];	
			 
			 // capitalized
			 strOut=[strOut stringByAppendingString:@" or bus_info like '%"];
			 strOut=[strOut stringByAppendingString:[str uppercaseString]];
			 strOut=[strOut stringByAppendingString:@"%'"];	
			 // lower string:				
			 strOut=[strOut stringByAppendingString:@" or bus_info like '%"];
			 strOut=[strOut stringByAppendingString:[str lowercaseString]];
			 strOut=[strOut stringByAppendingString:@"%'"];
			 
			 } 
						
			strOut=[strOut stringByAppendingString:@")"];
		}		
	}
	
	return strOut;
}

-(NSString*) separateByColonesAndAddToQueryName:(NSString*)sQuery splittingString:(NSString*)sString andFirst:(bool)bFirstIn
{
	NSArray* ar=[[NSString stringWithUTF8String:[sString UTF8String]] componentsSeparatedByString:@" "];
	NSString* strOut;
	bool bFirst=bFirstIn;
	for(id str in ar)
	{
		if(bFirst)
		{
			// 
			strOut=[NSString stringWithFormat:@"%@ or (bus_name like '%@", sQuery/* UTF8String]*/, @"%"];
			strOut=[strOut stringByAppendingString:str];
			strOut=[strOut stringByAppendingString:@"%'"];
			
			if([str length]>1)
			{
				// with upper letter:				
				strOut=[strOut stringByAppendingString:@" or bus_name like '%"];
				strOut=[strOut stringByAppendingString:[[str substringToIndex:1] uppercaseString]];
				strOut=[strOut stringByAppendingString:[[str substringFromIndex:1] lowercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];					
				// capitalized
				strOut=[strOut stringByAppendingString:@" or bus_name like '%"];
				strOut=[strOut stringByAppendingString:[str uppercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];	
				// lower string:				
				strOut=[strOut stringByAppendingString:@" or bus_name like '%"];
				strOut=[strOut stringByAppendingString:[str lowercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];				
			} 
			
			strOut=[strOut stringByAppendingString:@")"];			
			
			bFirst=false;			
		}
		else{
			strOut=[NSString stringWithFormat:@"%@ and (bus_name like '%@", strOut/*UTF8String]*/, @"%"];		
			strOut=[strOut stringByAppendingString:str];
			strOut=[strOut stringByAppendingString:@"%'"];
			
			if([str length]>1)
			{
				// with upper letter:
				
				strOut=[strOut stringByAppendingString:@" or bus_name like '%"];
				strOut=[strOut stringByAppendingString:[[str substringToIndex:1] uppercaseString]];
				strOut=[strOut stringByAppendingString:[[str substringFromIndex:1] lowercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];	
				
				// capitalized
				strOut=[strOut stringByAppendingString:@" or bus_name like '%"];
				strOut=[strOut stringByAppendingString:[str uppercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];	
				// lower string:				
				strOut=[strOut stringByAppendingString:@" or bus_name like '%"];
				strOut=[strOut stringByAppendingString:[str lowercaseString]];
				strOut=[strOut stringByAppendingString:@"%'"];
				
			} 
			
			strOut=[strOut stringByAppendingString:@")"];
		}		
	}
	
	return strOut;
}

#pragma mark -
#pragma mark U-Bahn
-(NSArray*) getAllStationsLineIdsInAppleFormat
{
    return _aiAllStationsLineIds;
}

-(NSArray*) getAllStationsIdsInAppleFormat
{
    return _aiAllStationsIds;
}

-(NSArray*) getAllStationsNameInAppleFormat
{
    return _aiAllStationsShown;
}

-(NSDictionary*) readUStationsAndOrderThemByLineNames
{
    NSString* strQuery;
    //first make an query for knowing all the stations:
    strQuery=[NSString stringWithString: @"select line_id, line_name from lines where shown=1 order by line_name;"];
    int nLinesCount=0;
    // get things rolling:
    sqlite3 *database;	
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	// Setup the SQL Statement and compile it for faster access
	sqlite3_stmt *compiledStatement;
	NSMutableArray** recordsInLines;
	NSMutableArray** IdsInLines;
	NSMutableArray* LineIds;
	NSMutableArray* lineNames;
	// first find out, how many records do we have:
	if(sqlite3_prepare_v2(database, "select count(*) from lines where shown=1", -1, &compiledStatement, NULL) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {			
		nLinesCount=sqlite3_column_int(compiledStatement, 0);
		
		// we need names of stations and their ids for returning them 
		// our base controller:
		recordsInLines=(NSMutableArray**)malloc(sizeof(NSMutableArray)*nLinesCount);
		IdsInLines=(NSMutableArray**)malloc(sizeof(NSMutableArray)*nLinesCount);

		lineNames=[NSMutableArray arrayWithCapacity: nLinesCount];
		LineIds=[NSMutableArray arrayWithCapacity: nLinesCount];
	    }
	    else{
		printf("Errors occured during loading strings for showing them in lines order\n");
		sqlite3_finalize(compiledStatement);
		sqlite3_close(database);
		return nil;
	    }
	}
	else{
	    printf("Errors occured during loading strings for showing them in lines order\n");
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	    return nil;
	}

	sqlite3_finalize(compiledStatement);

	// get lines and their ids:
	const char* queryLines=[strQuery UTF8String];
	if(sqlite3_prepare_v2(database, queryLines, -1, &compiledStatement, NULL) == SQLITE_OK)
	{
	    while(sqlite3_step(compiledStatement)==SQLITE_ROW)
	    {
		[LineIds addObject: 
				[NSString stringWithFormat:@"%d", sqlite3_column_int(compiledStatement, 0)]];
		[lineNames addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
	    }
	}
	else{
	    printf("Errors occured during loading strings for showing them in lines order\n");
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	    return nil;
	}

	sqlite3_finalize(compiledStatement);
	// now get all info about stations in lines:
	int nCount=0;
	for(id line_id in LineIds)
	{
	    if(!_bUseEnglishNames)
		strQuery=[NSString stringWithFormat: @"select id, station_name from stations where shown=1 and station_line_id=%@", line_id];
	    else

		strQuery=[NSString stringWithFormat: @"select id, station_nameEng from stations where shown=1 and station_line_id=%@", line_id];

	    //printf("Query for getting station sorted by lines: %s\n", [strQuery UTF8String]);
	    if(sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
	    {
		recordsInLines[nCount]=[NSMutableArray arrayWithCapacity: 30];
		IdsInLines[nCount]=[NSMutableArray arrayWithCapacity: 30];
		while(sqlite3_step(compiledStatement)==SQLITE_ROW)
		{
		    [IdsInLines[nCount] addObject: 
	    		[NSString stringWithFormat:@"%d", sqlite3_column_int(compiledStatement, 0)]];
		    [recordsInLines[nCount] addObject: 
		       [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];	    
		}
	    }
	    else{
		printf("Errors occured during loading strings for showing them in lines order\n");
		sqlite3_finalize(compiledStatement);
		sqlite3_close(database);
		return nil;
	    }
	    nCount++;
	    sqlite3_finalize(compiledStatement);
	}
	// now we've got all the object we wanted; 
	// form them to dictionaries:
	NSArray* stationNames=[NSArray arrayWithObjects: (NSArray**)recordsInLines count: nCount];
	NSArray* stationIds=[NSArray arrayWithObjects: (NSArray**)IdsInLines count: nCount];

	_diStationIds=[NSDictionary dictionaryWithObjects: stationIds forKeys: lineNames];
	[_diStationIds retain];
	
	NSDictionary* dictNames=[NSDictionary dictionaryWithObjects: stationNames forKeys: lineNames];
	[dictNames retain];

	// get info about loaded lines:
	_aiLineIds=LineIds;
	[_aiLineIds retain];
	// save line names for keys:
	/*
	_aiLineNames=lineNames;
	[_aiLineNames retain];
	*/
		free(recordsInLines);
		free(IdsInLines);

	return dictNames;
    }

    return nil;
}

-(NSArray*) readUStationsDrawInfoAsNSArray
{
    NSString* strQuery;
    NSMutableArray* aiDrawInfo;
    //first make an query for knowing all the stations:
    strQuery=[NSString stringWithString: @"select id_station, id_link_station, coord_x, coord_y from draw_info"];
    int nInfoCount=0;
    // get things rolling:
    sqlite3 *database;	

    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	// Setup the SQL Statement and compile it for faster access
	sqlite3_stmt *compiledStatement;
	
	// first find out, how many records we have:
	if(sqlite3_prepare_v2(database, "select count(*) from draw_info", -1, &compiledStatement, NULL) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {			
		nInfoCount=sqlite3_column_int(compiledStatement, 0);
		if(_aiDrawInfo!=nil)
		{
		    [_aiDrawInfo release];
		    _aiDrawInfo=nil;
		}

		aiDrawInfo=[NSMutableArray arrayWithCapacity: nInfoCount];
	    }
	    else{
		printf("Errors occured during loading strings for showing them in lines order\n");
		sqlite3_finalize(compiledStatement);
		sqlite3_close(database);
		return nil;
	    }
	}
	else{
	    printf("Errors occured during loading strings for showing them in lines order\n");
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	    return nil;
	}

	sqlite3_finalize(compiledStatement);

	// get lines and their ids:
	const char* queryInfo=[strQuery UTF8String];
	if(sqlite3_prepare_v2(database, queryInfo, -1, &compiledStatement, NULL) == SQLITE_OK)
	{
	    NSArray *keys = [NSArray arrayWithObjects: kId, kLinkId, kX, kY, nil];
	    while(sqlite3_step(compiledStatement)==SQLITE_ROW)
	    {
		NSNumber* nId=[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 0)];
		NSNumber* nIdLink=[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 1)];
		NSNumber* nX=[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 2)];
		NSNumber* nY=[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 3)];

		NSArray *objects = [NSArray arrayWithObjects: nId, nIdLink, nX, nY, nil];
		NSDictionary* dict=[NSDictionary dictionaryWithObjects:objects forKeys:keys];
		
		[aiDrawInfo addObject: dict];
	    }
	}
	else{
	    printf("Errors occured during loading strings for showing them in lines order\n");
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	    return nil;
	}
	sqlite3_finalize(compiledStatement);
    }
    sqlite3_close(database);

    _aiDrawInfo=aiDrawInfo;
    [_aiDrawInfo retain];
    
    return _aiDrawInfo;
}

-(NSArray*) getUStationsLineIdsUsedInStationsSortedByLine
{
    return _aiLineIds;
}

-(NSDictionary*) getUStationIdsSortedByLine
{
    return _diStationIds;
}

-(NSArray*) readUStationsAsNSArray
{
    return [self readUStationsAsNSArrayAndOrderAlpabetically: false];
}

-(void) cleanAllResourcesOfUStationNamesWithAlpOrd
{
    if(_aiAllStationsShown!=nil)
	[_aiAllStationsShown release];
    _aiAllStationsShown=nil;

    if(_aiAllStationsLineIds!=nil)
	[_aiAllStationsLineIds release];
    _aiAllStationsLineIds=nil;

    /*
    if(_aiAllStationsIds!=nil)
	[_aiAllStationsIds release];
    _aiAllStationsIds=nil;

    if(_aiAllStationsLineIds!=nil)
	[_aiAllStationsLineIds release];
    _aiAllStationsLineIds=nil;
    */

    if(_aiUStations!=nil)	
	[_aiUStations release];
    _aiUStations=nil;

    if(_aiULineNames!=nil)
	[_aiULineNames release];
    _aiULineNames=nil;

    if(_aiiULineNumbers!=nil)
	[_aiiULineNumbers release];
    _aiiULineNumbers=nil;

    if(_aiiUStationsNotShown!=nil)
	[_aiiUStationsNotShown release];
    _aiiUStationsNotShown=nil;

    if(_aiiUStationIds!=nil)
	[_aiiUStationIds release];
    _aiiUStationIds=nil;

    _nUStationsCount=0;
}

-(NSArray*) readUStationsAsNSArrayAndOrderAlpabetically: (bool)alp
{
    NSString* strQuery;
    strQuery=[NSString stringWithFormat:@"from stations S join lines L on L.line_id=S.station_line_id"];
    
    if(alp){
	if(!_bUseEnglishNames)
	strQuery=[NSString stringWithFormat:@"%@ %@", strQuery, @"order by station_name"];
	else
	strQuery=[NSString stringWithFormat:@"%@ %@", strQuery, @"order by station_nameEng"];
    }

    // arrays to store the received elements:
    NSMutableArray* aiUStations; 
    NSMutableArray* aiULineNames;
    // I need line numbers for working Cyclon-algorithm
    // and it's written in C, so I leave it as an array:
    NSMutableArray* aiiULineNumbers;
    NSMutableArray* aiiUStationsNotShown;
    NSMutableArray* aiiUStationIds;

    //printf("Query for UStations: is %s\n", [strQuery UTF8String]);
    sqlite3 *database;	
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

	sqlite3_stmt *compiledStatement;
	// Setup the SQL Statement and compile it for faster access
	// first find out, how many records do we have:
    	NSString* strQueryCount=[NSString stringWithFormat:@"%@ %@", @"select count(*)", strQuery];

	const char *sqlStatementHowMany = [strQueryCount UTF8String];
	//printf("Query to U-bahn station name:%s\n", [strQueryCount UTF8String]);
	if(sqlite3_prepare_v2(database, sqlStatementHowMany, -1, &compiledStatement, NULL) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		// I need to free all that resources manually:
		// Really could move you to memory leaks!
		//[self cleanAllResourcesOfUStationNamesWithAlpOrd];
		_nUStationsCount=sqlite3_column_int(compiledStatement,0);
		//printf("Count is: %d\n", _nUStationsCount);
		aiUStations=[NSMutableArray arrayWithCapacity: _nUStationsCount];
		aiULineNames=[NSMutableArray arrayWithCapacity: _nUStationsCount];
		aiiULineNumbers=[NSMutableArray arrayWithCapacity: _nUStationsCount];
		aiiUStationIds=[NSMutableArray arrayWithCapacity: _nUStationsCount];

		if(sqlite3_prepare_v2(database, "select count(*) from stations where shown=0",
			    -1, &compiledStatement, NULL) == SQLITE_OK) {

		    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {			
			_nUStationNotShownCount=sqlite3_column_int(compiledStatement,0);				
			aiiUStationsNotShown=[NSMutableArray arrayWithCapacity: _nUStationNotShownCount];
		    }
		    else{
			printf("Problems with getting info about not showing stations!\n");
		    }
		}
	    }
	    else{
		printf("Problems occured! Exit\n");
		sqlite3_finalize(compiledStatement);
		sqlite3_close(database);
		return nil;
	    }
	    sqlite3_finalize(compiledStatement);


	    //get the rows themselves:
	NSString* strQueryMain; 
     	if(!_bUseEnglishNames)
	strQueryMain=[NSString stringWithFormat:@"%@ %@", @"select station_name, line_name, line_id, id, S.shown", strQuery];
	else
	strQueryMain=[NSString stringWithFormat:@"%@ %@", @"select station_nameEng, line_name, line_id, id, S.shown", strQuery];

	const char *sqlStatement= [strQueryMain UTF8String];
	//printf("Query to U-bahn station name:%s\n", [strQueryMain UTF8String]);
	if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
	    while(sqlite3_step(compiledStatement) == SQLITE_ROW) {

		[aiUStations addObject: [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]];

		[aiULineNames addObject: [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
		[aiiULineNumbers addObject: [NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 2)]];

		NSNumber* num=[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 3)-1];
		//printf("Received number: %d\n", [num intValue]);
		//[num retain];
		[aiiUStationIds addObject: num];
		//[num retain];


		if(sqlite3_column_int(compiledStatement, 4)==0 && ![aiUStations containsObject: num]){
		    //printf("adding not showing object %d\n", [num stringValue]);
		    [aiiUStationsNotShown addObject: num];
		}
		//[num release];
	    }
	}
	else{
		sqlite3_finalize(compiledStatement);
		sqlite3_close(database);
	    printf("Problems occured!\n");
		return nil;
	}
	sqlite3_finalize(compiledStatement);
	}	
    }
    sqlite3_close(database);

    _nUStationsCount = [aiUStations count];

    // store them as members of class:
    _aiUStations=aiUStations;
    [_aiUStations retain];

    _aiULineNames=aiULineNames;
    [_aiULineNames retain];

    _aiiULineNumbers=aiiULineNumbers;
    [_aiiULineNumbers retain];
    _aiiUStationsNotShown=aiiUStationsNotShown;
    [_aiiUStationsNotShown retain];

    _aiiUStationIds=aiiUStationIds;
    [_aiiUStationIds retain];

    return aiUStations;
}

-(NSDictionary*) readUStationsAsNSArrayAndFormThemAlpabetically
{
    // first get all the names;
    NSArray* aiUStations;
    if(!_bStationsInAlpabeticalOrderWereLoaded){
	if(_aiiUStationsNotShown!=nil){
	    [_aiiUStationsNotShown release];
	    _aiiUStationsNotShown=nil;
	}
	aiUStations=[self readUStationsAsNSArrayAndOrderAlpabetically: true];
	_bStationsInAlpabeticalOrderWereLoaded=true;
    }
    else
	aiUStations = _aiUStations;
   
    // then go through the array and form indexes for the table:
    NSMutableArray* aLetters=[NSMutableArray arrayWithCapacity:33]; // that would be keys;
    // and we need values for them:
    NSMutableArray** aValues=(NSMutableArray**)malloc(sizeof(NSMutableArray)*33);
    // and the names of the lines:
    NSMutableArray** aLineNumbers=(NSMutableArray**)malloc(sizeof(NSMutableArray)*33);
    // ...and ids of the stations:
    NSMutableArray** aStationNumbers=(NSMutableArray**)malloc(sizeof(NSMutableArray)*33);
    NSMutableArray* allStationsShown=[NSMutableArray arrayWithCapacity: _nUStationsCount];
    NSMutableArray* allStationsIds=[NSMutableArray arrayWithCapacity: _nUStationsCount];
    NSMutableArray* allStationsLineIds=[NSMutableArray arrayWithCapacity: _nUStationsCount];
  
    NSString* lastLetter=@"";
    int nCurIndex=-1;
	/*
	printf("Not shown:\n");
	for(id num in _aiiUStationsNotShown)
	{
	    printf("Num: %d\n", [num intValue]);
	}
	*/
    for(int i=0; i<_nUStationsCount; i++)
    {
	// get the only the first letter;
	NSString* curLetter=[[[aiUStations objectAtIndex: i] substringToIndex:1] uppercaseString];
	//check if the number is out of db:
	
  	if([_aiiUStationsNotShown containsObject: [_aiiUStationIds objectAtIndex: i]])
      		continue; 
	/*
	bool bFoundNotShownNode=false;
	for(int j=0; j<[_aiiUStationsNotShown count]; j++)
	    if([[_aiiUStationsNotShown objectAtIndex: j] intValue]==i)
	    {bFoundNotShownNode=true; break;} 
	if(bFoundNotShownNode)continue;
	*/

	// add station to the whole station list:
	[allStationsShown addObject: [aiUStations objectAtIndex:i]];
	// add id of the station as a string, because apple cannot store 
	// normal integer values:
	//	
	[allStationsIds addObject: [_aiiUStationIds objectAtIndex: i]];
	[allStationsLineIds addObject: [_aiiULineNumbers objectAtIndex: i]];
	
	// if we've started another letter:
	if(![lastLetter isEqualToString:curLetter])
	{
	    [aLetters addObject: curLetter];
	    aValues[++nCurIndex]=[NSMutableArray arrayWithCapacity:20];
	    aLineNumbers[nCurIndex]=[NSMutableArray arrayWithCapacity:20];
	    aStationNumbers[nCurIndex]=[NSMutableArray arrayWithCapacity:20];
	    //[aValues[nCurIndex] retain];
	    //printf("Adding letter: %s\n", [curLetter UTF8String]);
	    lastLetter=curLetter;
	}
	[aValues[nCurIndex] addObject: [aiUStations objectAtIndex:i]];
	[aLineNumbers[nCurIndex] addObject:[_aiiULineNumbers objectAtIndex: i]];
	[aStationNumbers[nCurIndex] addObject:[_aiiUStationIds objectAtIndex: i]];
    }
    // now we've got indexes and values, add them to the final array:
    NSArray* objects=[NSArray arrayWithObjects:(NSArray**)aValues count: nCurIndex+1];
    NSArray* LineNames=[NSArray arrayWithObjects:(NSArray**)aLineNumbers count: nCurIndex+1];
    NSArray* StatIds=[NSArray arrayWithObjects:(NSArray**)aStationNumbers count: nCurIndex+1];
    NSDictionary* dict=[NSDictionary dictionaryWithObjects: objects forKeys:(NSArray*)aLetters];
    // here we would collect indexes to our line numbers:
    _diULineNumbers=[NSDictionary dictionaryWithObjects: LineNames forKeys:(NSArray*)aLetters];
    [_diULineNumbers retain];
    _diUStationNumbers=[NSDictionary dictionaryWithObjects: StatIds forKeys:(NSArray*)aLetters];
    [_diUStationNumbers retain];
    
    // and do not release all station names, please, I'll do it manually:
    _aiAllStationsShown=allStationsShown;
    [_aiAllStationsShown retain];
    _aiAllStationsIds=allStationsIds;
    [_aiAllStationsIds retain];
    _aiAllStationsLineIds=allStationsLineIds;
    [_aiAllStationsLineIds retain];

    
    free(aLineNumbers);
    free(aValues);
	free(aStationNumbers);
    //free(aLetters);

    return dict;
}

-(void) releaseUStationAsNSArrayResources
{
    if(_aiUStations!=nil)
	[_aiUStations release];
    if(_aiULineNames!=nil)
	[_aiULineNames release];
    if(_aiiULineNumbers!=nil)
	[_aiiULineNumbers release];
    if(_aiiUStationIds!=nil)
	[_aiiUStationIds release];
    if(_aiiUStationsNotShown!=nil)
	[_aiiUStationsNotShown release];

    //set them to nil:
    _aiUStations=nil;
    _aiULineNames=nil;
    _aiiUStationIds=nil;
    _aiiULineNumbers=nil;
    _aiiUStationsNotShown=nil;
}

-(NSArray*) getUStationIdsAsNSArray
{
    return _aiiUStationIds;
}

-(NSArray*) getUStationNotShownAsNSArray
{
    return _aiiUStationsNotShown;
}

-(NSArray*) getULineNamesAsNSArray
{
    return _aiULineNames;
}

-(NSArray*) getULineNumbersAsNSArray
{
    return _aiiULineNumbers;
}

-(NSUInteger) getNotShownStationsCount
{
	return _nUStationNotShownCount;
}

-(NSDictionary*) getUStationNumbersSortedAlp
{
    return _diUStationNumbers;
}

-(NSDictionary*) getULineNumbersSortedAlp
{
    return _diULineNumbers;
}

-(NSUInteger) getUStationsCount
{
    return _nUStationsCount;
}

-(NSUInteger) getUStationsCountOfAllowedLinesWithStart: (int) nStart andEnd: (int) nEnd
{
    NSString* strQuery=[NSString stringWithFormat: @"select count(*) from linesinterconnections where idLine=%d and idLineTo=%d or idLine=%d and idLineTo=%d;", 
	nStart, nEnd, nEnd, nStart];
    
    int nAmount=0;

    sqlite3 *database;
    // Open the database 
    int error;
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	sqlite3_stmt *compiledStatement;
	// first get amount of records:
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		nAmount=sqlite3_column_int(compiledStatement, 0);
	    }
	}
	else{
	    printf("getUStationsCountOfAllowedLinesWithStart: Cannot execute a query! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	}
	// Release the compiled statement from memory
	sqlite3_finalize(compiledStatement);		
    }
    sqlite3_close(database);

    return nAmount;
}

-(int*) getUStationsAllowedLinesWithStart: (int) nStart andEnd: (int) nEnd andIndex: (int) nIndex
{
    NSString* strQuery=[NSString stringWithFormat: @"select idLine, idLineTo, idLineBetween from linesinterconnections where idLine=%d and idLineTo=%d or idLine=%d and idLineTo=%d;", 
	nStart, nEnd, nEnd, nStart];
    
    sqlite3 *database;
    // Open the database 
    int error;
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	sqlite3_stmt *compiledStatement;
	// first get amount of records:
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    int nCount=0;
	    while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		if(nCount==nIndex)
		{
		    int id1=sqlite3_column_int(compiledStatement, 0);
		    int id2=sqlite3_column_int(compiledStatement, 1);
		    int between=sqlite3_column_int(compiledStatement, 2);

		    int* anLines;
		    if(between!=0){
		    anLines=(int*)malloc(sizeof(int)*3);
		    anLines[2]=between;
		    _nCountOfAllowedLines=3;
		    }
		    else{
		    anLines=(int*)malloc(sizeof(int)*2);
		    _nCountOfAllowedLines=2;
		    }

		    anLines[0]=id1;
		    anLines[1]=id2;

		    sqlite3_finalize(compiledStatement);
		    sqlite3_close(database);

		    return anLines;
		} 
		nCount++;
	    }
	}
	else{
	    printf("getUStationsCountOfAllowedLinesWithStart: Cannot execute a query! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	}
	// Release the compiled statement from memory
	sqlite3_finalize(compiledStatement);		
    }
    sqlite3_close(database);

    return NULL;
}

-(int) getUStationsCountOfAllowedLinesArray
{
    return _nCountOfAllowedLines;
}

#pragma mark -
#pragma mark SightSeeing

-(NSArray*) getSightseeingForNumbers:(NSArray*)aiNumbers
{
    NSMutableArray* aiSightCaptions;
    NSMutableArray* aiSightDetail;
    NSMutableArray* aiSightType;
    NSMutableArray* aiSightStationId;

    // prepare our query with numbers we have:
    NSString* sQueryAdd;
    // init add query:
    sQueryAdd=[NSString stringWithFormat: @"where station_id=%d", 
	       [[aiNumbers objectAtIndex: 0] intValue]];

    for(int i=1; i<[aiNumbers count]; i++)
    {
	sQueryAdd = [NSString stringWithFormat: @"%@ or station_id=%d", sQueryAdd,  
		     [[aiNumbers objectAtIndex: i] intValue]];
    }

    // Setup the database object
    sqlite3 *database;
    // Open the database 
    int error;
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	sqlite3_stmt *compiledStatement;
	// first get amount of records:
	NSString *strQuery=[NSString stringWithString:@"select count(*) from sights"];
	strQuery=[NSString stringWithFormat: @"%@ %@", strQuery, sQueryAdd]; 
	//printf("Query for sightseeings: %s\n", [strQuery UTF8String]);

	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		[self releaseAllSightSeeing];
		int nAmount=sqlite3_column_int(compiledStatement, 0);
		aiSightCaptions=[NSMutableArray arrayWithCapacity: nAmount];
		aiSightType=[NSMutableArray arrayWithCapacity: nAmount];
		aiSightDetail=[NSMutableArray arrayWithCapacity: nAmount];
		aiSightStationId=[NSMutableArray arrayWithCapacity: nAmount];
	    }
	}
	else{
	    printf("getSightseeingForNumbers: Cannot execute a query! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	}
	// Release the compiled statement from memory
	sqlite3_finalize(compiledStatement);		
	//type integer,"sight_caption" varchar, "sight_detail

	NSRange range=[databaseName rangeOfString: @"Railway" options:NSCaseInsensitiveSearch];
	if(range.location==NSNotFound){
	    // it's an Underground database;
	    strQuery=[NSString stringWithString:@"select type, sight_caption, sight_detail, St.station_name from sights S"];
	    strQuery=[NSString stringWithFormat: @"%@ join stations St on St.id=S.station_id", strQuery];
	    strQuery=[NSString stringWithFormat: @"%@ %@", strQuery, sQueryAdd];
	}
	else
	{
	    // it's an Railways database;
	    strQuery=[NSString stringWithString:@"select type, sight_caption, sight_detail, St.station_name from sights S"];
	    strQuery=[NSString stringWithFormat: @"%@ join %@_stations St on St.station_id=S.station_id", strQuery, 
		namePrefix];
	    strQuery=[NSString stringWithFormat: @"%@ %@", strQuery, sQueryAdd];
	}
	printf("getSightseeingForNumbers query: %s\n", [strQuery UTF8String]);
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    // go through the records:
	    while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		[aiSightType addObject: 
		    [NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 0)]];
		[aiSightCaptions addObject:
		    [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
		[aiSightDetail addObject:
	    		[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)]];
		[aiSightStationId addObject:
	  		[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)]];

	    }
	}
	else{
	    printf("getSightseeingForNumbers: Cannot execute a query at second time! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	}
	sqlite3_finalize(compiledStatement);
    }
    else
	printf("getSightseeingForNumbers: cannot open database!\n");
    sqlite3_close(database);

    _aiSightTypes=aiSightType;
    [_aiSightTypes retain];

    _aiSightDetail = aiSightDetail;
    [_aiSightDetail retain];

    _aiSightCaptions = aiSightCaptions;
    [_aiSightCaptions retain];

    _aiSightStationId = aiSightStationId;
    [_aiSightStationId retain];

    return _aiSightCaptions;
}

-(NSArray*) getSightTypes
{
    return _aiSightTypes;
}

-(NSArray*) getSightDetails
{
    return _aiSightDetail;
}

-(NSArray*) getSightCaptions
{
    return _aiSightCaptions;
}

-(NSArray*) getSightStationIds
{
    return _aiSightStationId;
}

-(void) releaseAllSightSeeing
{
    if(_aiSightCaptions)
	[_aiSightCaptions release];
    if(_aiSightDetail)
	[_aiSightDetail release];
    if(_aiSightTypes)
	[_aiSightTypes release];
    if(_aiSightStationId!=nil)
	[_aiSightStationId release];

    _aiSightStationId=nil;
    _aiSightTypes=nil;
    _aiSightDetail=nil;
    _aiSightCaptions=nil;
}

// unforunately I cannot use the upper procedure,
// And I have to make another procedure for releasing 
// my elements;
-(NSArray*) getSightseeingAllStationIdsOnly
{
    // here We would use only stations' ids!
    NSMutableArray* aiSightStationId;
    _nAmountSightSeeing=0;
        
    // Setup the database object
    sqlite3 *database;
    // Open the database 
    int error;
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	sqlite3_stmt *compiledStatement;
	// first get amount of records:
	NSString *strQuery=[NSString stringWithString:@"select count(*) from sights group by station_id"];
	//printf("Query for sightseeings: %s\n", [strQuery UTF8String]);
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		[self releaseAllSightSeeingStationIDs];
		_nAmountSightSeeing=sqlite3_column_int(compiledStatement, 0);
		//printf("The count of our array is: %d\n", _nAmountSightSeeing);
		aiSightStationId=[NSMutableArray arrayWithCapacity: _nAmountSightSeeing];
	    }
	}
	else{
	    printf("getSightseeingAllStationIdsOnly Cannot execute a query! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	}
	// Release the compiled statement from memory
	sqlite3_finalize(compiledStatement);

	strQuery=[NSString stringWithString:@"select station_id from sights group by station_id"];
	//printf("getSightseeingAllStationIdsOnly query: %s\n", [strQuery UTF8String]);
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    // go through the records:
	    while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		[aiSightStationId addObject:
	     		[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 0)]];
	    }
	}
	else{
	    printf("getSightseeingAllStationIdsOnly Cannot execute a query at second time! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);
	}
	sqlite3_finalize(compiledStatement);
    }
    else
	printf("getSightseeingAllStationIdsOnly cannot open database!\n");
    sqlite3_close(database);

    if(_nAmountSightSeeing){
	_aiSSStationIds = aiSightStationId;
	[_aiSSStationIds retain];
    }
    else
	return nil;

    return _aiSSStationIds;
}

// I've used only station ids, release them!
-(void) releaseAllSightSeeingStationIDs
{
    if(_aiSSStationIds!=nil)
	[_aiSSStationIds release];
    _aiSSStationIds=nil;
    _nAmountSightSeeing=0;
}

-(int) getAmountOfSightSeeingStationIds
{
    return _nAmountSightSeeing;
}

-(void) releaseUStation2StationResources
{
    if(_aiNodes!=nil)
	[_aiNodes release];
    _aiNodes=nil;

    if(_aiCyclonLineNubmers!=nil)
	[_aiCyclonLineNubmers release];
    _aiCyclonLineNubmers=nil;
}

-(NSArray*) readUStationToStationStructure
{
    NSMutableArray* aiNodes;// here we would save all data, related to old Knots-structure;
    NSMutableArray* aiLineNumbers;

    // Setup the database object
    sqlite3 *database;
    // Open the database 
    int error;
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
	sqlite3_stmt *compiledStatement;
	// first get amount of records:
	NSString *strQuery=[NSString stringWithString:@"select count(*) from stations"];
	//printf("Query for sightseeings: %s\n", [strQuery UTF8String]);
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK) {
	    if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
		[self releaseUStation2StationResources];
		aiNodes=[NSMutableArray arrayWithCapacity: sqlite3_column_int(compiledStatement, 0)];
		aiLineNumbers=[NSMutableArray arrayWithCapacity: sqlite3_column_int(compiledStatement, 0)];
	    }
	}
	else{
	    printf("readUStationToStationStructure: Cannot execute a query! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);

	    return nil;
	}
	// Release the compiled statement from memory
	sqlite3_finalize(compiledStatement);

	//acquire them all:
	strQuery=[NSString stringWithString: @"select id_station, id_link_station, link_weight from station_to_station order by id_station"];
	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK){
	    int nCurNode=-1;
	    NSMutableArray* aiNode;
	    while(sqlite3_step(compiledStatement)==SQLITE_ROW){
		int nNode=sqlite3_column_int(compiledStatement, 0);
		if(nCurNode==-1)
		{
		    nCurNode=nNode;
		    aiNode=[NSMutableArray arrayWithCapacity: 5];
		}

		if(nNode != nCurNode && nCurNode!=-1){
		    nCurNode=nNode;

		    // add old aiNode to the big structure:
		    [aiNodes addObject: aiNode];
		    // create another one collection:
		    aiNode=[NSMutableArray arrayWithCapacity: 5];
		}

		NSMutableDictionary* diObject=[NSMutableDictionary dictionaryWithCapacity: 2];
		[diObject setObject: [NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 1)]
		    forKey: kKnot];
		[diObject setObject: [NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 2)]
		     forKey: kWeight];

		// add it to the whole knot:
		[aiNode addObject: diObject];
	    }
	    // and you have to add the last one object:

	    [aiNodes addObject: aiNode];
	}
	else{
	    printf("readUStationToStationStructure: Cannot execute a query for the whole structure! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);

	    return nil;
	}

	sqlite3_finalize(compiledStatement);


	// get the line numbers:
	strQuery = [NSString stringWithString: @"select station_line_id from stations"];

	if((error=sqlite3_prepare_v2(database, [strQuery UTF8String], -1, &compiledStatement, NULL)) == SQLITE_OK){
	    while(sqlite3_step(compiledStatement)==SQLITE_ROW){
		[aiLineNumbers addObject: 
	  		[NSNumber numberWithInt: sqlite3_column_int(compiledStatement, 0)]];
	    }
	}
	else{
	    printf("readUStationToStationStructure: Cannot execute a query for the line numbers structure! Error: %d\n", error);
	    sqlite3_finalize(compiledStatement);
	    sqlite3_close(database);

	    return nil;
	}

	sqlite3_finalize(compiledStatement);
    }
    sqlite3_close(database);

    _aiNodes=aiNodes;
    [_aiNodes retain];


    _aiCyclonLineNubmers=aiLineNumbers;
    [_aiCyclonLineNubmers retain];

    return _aiNodes;
}

-(NSArray*) getCycloneLineNumbers
{
    return _aiCyclonLineNubmers;
}
@end
